package com.nineclock.document.service.impl;
import com.google.common.collect.Lists;
import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.nineclock.common.entity.PageResult;
import com.nineclock.common.enums.ResponseEnum;
import com.nineclock.common.exception.NcException;
import com.nineclock.common.filter.CurrentUserHolder;
import com.nineclock.common.utils.BeanHelper;
import com.nineclock.document.dto.*;
import com.nineclock.document.enums.DocumentPermissionEnum;
import com.nineclock.document.mapper.DocCollaborationsMapper;
import com.nineclock.document.mapper.DocFileMapper;
import com.nineclock.document.mapper.DocFolderMapper;
import com.nineclock.document.pojo.DocCollaborations;
import com.nineclock.document.pojo.DocFile;
import com.nineclock.document.pojo.DocFolder;
import com.nineclock.document.service.DocFileService;
import com.nineclock.system.feign.SysCompanyUserFeign;
import com.nineclock.system.dto.SysCompanyUserDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Transactional
public class DocFileServiceImpl implements DocFileService {

    @Autowired
    private DocFolderMapper folderMapper;

    @Autowired
    private DocFileMapper fileMapper;

    @Autowired
    private SysCompanyUserFeign companyUserFeign;

    @Autowired
    private DocCollaborationsMapper collaborationsMapper;


    @Override
    public DocumentDto queryFolderAndFile(Long parentFoldId) {

        // 1、查询当前目录下的所有文件夹列表
        List<DocFolderDto> folderDtoList = queryFolders(parentFoldId);

        // 2、查询当前目录下所有的文件列表
        List<DocFileDto> fileDtoList = queryFiles(parentFoldId);

        // 3、封装返回数据到DocumentDto
        DocumentDto documentDto = new DocumentDto();
        documentDto.setFolders(folderDtoList);
        documentDto.setFiles(fileDtoList);

        return documentDto;
    }


    /**
     * 查询当前目录下所有的文件列表
     *
     * @param parentFoldId
     * @return
     */
    private List<DocFileDto> queryFiles(Long parentFoldId) {

        List<DocFile> fileList = new ArrayList<>();

        // 1、查询文件是公共读、公共读写
        LambdaQueryWrapper<DocFile> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(DocFile::getFolderId, parentFoldId);
        wrapper1.eq(DocFile::getStatus, 1);
        wrapper1.in(DocFile::getPermission, DocumentPermissionEnum.ALL_READ.getPermission(), DocumentPermissionEnum.ALL_READ_WRITE.getPermission());
        List<DocFile> docFileList1 = fileMapper.selectList(wrapper1);

        if (!CollectionUtils.isEmpty(docFileList1)) {
            fileList.addAll(docFileList1);
        }

        // 2、查询文件是私有，且当前登录用户是作者的
        LambdaQueryWrapper<DocFile> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(DocFile::getFolderId, parentFoldId);
        wrapper2.eq(DocFile::getStatus, 1);
        wrapper2.eq(DocFile::getPermission, DocumentPermissionEnum.PRIVATE_READ_WRITE.getPermission());
        wrapper2.eq(DocFile::getCreateUserId, CurrentUserHolder.get().getCompanyUserId());
        List<DocFile> docFileList2 = fileMapper.selectList(wrapper2);

        if (!CollectionUtils.isEmpty(docFileList2)) {
            fileList.addAll(docFileList2);
        }

        // 3、查询当前用户是协作者的文件
        List<DocFile> docFileList3 = fileMapper.selectFileListByCollaboration(parentFoldId, CurrentUserHolder.get().getCompanyUserId());

        if (!CollectionUtils.isEmpty(docFileList3)) {
            fileList.addAll(docFileList3);
        }

        // 查出来的文件可能重复，例如既是公共读写的又是协作者
        Set<DocFile> docFileSet = new HashSet<>(fileList);

        // 通过stream流，遍历set集合，将每个元素转成DocFileDto，最后封装为一个list集合

//        List<DocFileDto> fileDtoList = new ArrayList<>();
//        for (DocFile docFile : docFileSet) {
//            DocFileDto docFileDto = new DocFileDto();
//            fileDtoList.add(docFileDto);
//        }


        List<DocFileDto> fileDtoList = docFileSet.stream().map(docFile -> {

            DocFileDto docFileDto = BeanHelper.copyProperties(docFile, DocFileDto.class);

            // 根据创建人员工id查询系统微服务的feign接口，得到员工名称
            SysCompanyUserDTO companyUserDTO = companyUserFeign.queryCompanyUserById(docFileDto.getCreateUserId()).getData();
            if (companyUserDTO != null) {
                docFileDto.setUserName(companyUserDTO.getUserName());
            }

            // 根据更新人员工id查询系统微服务的feign接口，得到员工名称
            SysCompanyUserDTO companyUserDTO2 = companyUserFeign.queryCompanyUserById(docFileDto.getUpdateUserId()).getData();
            if (companyUserDTO2 != null) {
                docFileDto.setUpdateUserName(companyUserDTO2.getUserName());
            }

            return docFileDto;

        }).collect(Collectors.toList());

        return fileDtoList;

    }


    /**
     * 查询当前目录下的所有文件夹列表
     *
     * @param parentFoldId
     * @return
     */
    private List<DocFolderDto> queryFolders(Long parentFoldId) {
        LambdaQueryWrapper<DocFolder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DocFolder::getParentId, parentFoldId);
        wrapper.eq(DocFolder::getStatus, 1);
        List<DocFolder> folderList = folderMapper.selectList(wrapper);
        return BeanHelper.copyWithCollection(folderList, DocFolderDto.class);
    }


    @Override
    public DocFileDto getFileByFileId(Long id) {
        // 参数校验
        if (id == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        DocFile docFile = fileMapper.selectById(id);

        return BeanHelper.copyProperties(docFile, DocFileDto.class);
    }

    @Override
    public void changeStatus(Long fileId, Short status) {
        if (fileId == null && status == null) {
            throw new NcException(ResponseEnum.INVALID_PARAM_ERROR);
        }
        DocFile docFile = new DocFile();
        docFile.setStatus(status);
        //根据文件查询文件状态，然后修改
        LambdaQueryWrapper<DocFile> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DocFile::getId, fileId);
        fileMapper.update(docFile, wrapper);
    }

    @Override
    public PageResult<DocFileDto> queryPagingFile(String keyword, Integer page, Integer pageSize) {
        //创建分页对象
        IPage<DocFile> iPage = new Page<>(page, pageSize);
        //根据当前用户公司id查询文档列表
        LambdaQueryWrapper<DocFile> wrapper=new LambdaQueryWrapper<>();
        wrapper.eq(DocFile::getCompanyId,CurrentUserHolder.get().getCompanyId());
        //模糊匹配
        wrapper.like(DocFile::getName,keyword);
        iPage = fileMapper.selectPage(iPage, wrapper);
        //查询当前页
        List<DocFile> docFileList = iPage.getRecords();
        //数据转换
        List<DocFileDto> fileDtoList = docFileList.stream().map(docFile -> {
            //根据文档创建者id查询作者
            SysCompanyUserDTO companyUserDTO = companyUserFeign.queryCompanyUserById(docFile.getCreateUserId()).getData();
            LambdaQueryWrapper<DocCollaborations> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(DocCollaborations::getFileId, docFile.getId());
            List<DocCollaborations> collaborationsList = collaborationsMapper.selectList(wrapper1);

            List<SysCompanyUserDTO> companyUserDTOList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(collaborationsList)){
                companyUserDTOList = collaborationsList.stream().map(docCollaborations -> {
                    SysCompanyUserDTO sysCompanyUserDTO = new SysCompanyUserDTO();
                    sysCompanyUserDTO.setUserId(docCollaborations.getCollaborationId());
                    SysCompanyUserDTO userDTO = companyUserFeign.queryCompanyUserById(sysCompanyUserDTO.getUserId()).getData();
                    if (userDTO != null) {
                        userDTO.setUserName(userDTO.getUserName());
                    }
                    return userDTO;
                }).collect(Collectors.toList());
            }
            DocFileDto docFileDto = new DocFileDto();
            docFileDto.setId(docFile.getId());
            docFileDto.setName(docFile.getName());
            docFileDto.setFilePath(docFile.getFilePath());
            docFileDto.setFileSize(docFile.getFileSize());
            docFileDto.setStatus(docFile.getStatus());
            docFileDto.setUpdateTime(docFile.getUpdateTime());
            if (companyUserDTO!=null){
                docFileDto.setCreator(companyUserDTO);
                docFileDto.setUserName(companyUserDTO.getUserName());
            }
            docFileDto.setCollaborations(companyUserDTOList);

            return docFileDto;
        }).collect(Collectors.toList());
        return new PageResult<>(iPage.getTotal(), iPage.getPages(), fileDtoList);
    }

}
